{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "f802e64d-4eaa-445d-a48a-1042a91bc394",
   "metadata": {
    "tags": []
   },
   "source": [
    "# 基于AgentRuntime服务化组件\n",
    "\n",
    "## 目标\n",
    "使用 AgentRuntime 对组件进行服务化。\n",
    "\n",
    "AgentRuntime 是对组件（Component）的服务化封装，具体有如下几个功能：\n",
    "- 一键服务化组件: 使得组件能够以服务的形式运行，支持 API 调用和对话框交互。\n",
    "- Session 数据管理: 提供 Session 数据的管理功能，允许跟踪和存储用户会话数据。\n",
    "- 请求时鉴权: 支持在请求时进行认证，确保安全性。\n",
    "\n",
    "\n",
    "## 准备工作\n",
    "### 安装Python SDK\n",
    "\n",
    "appbuilder 支持使用 pip 安装（要求Python >= 3.8），并且 AgentRuntime 服务化组件依赖 `appbuilder-sdk[serve]`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2939356f-61c2-42e9-9e0c-fc6729c193f6",
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "pip install appbuilder-sdk 'appbuilder-sdk[serve]'"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "aeb2fa55-075f-48df-a9fb-8b40d9900684",
   "metadata": {},
   "source": [
    "## 基本用法\n",
    "\n",
    "### 快速开始\n",
    "\n",
    "下面的示例会基于 Playground 组件，在 8091 端口部署 Web 服务: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "41559341-fd7a-478c-a08b-1477d79e9d41",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-12-18T06:24:26.982459Z",
     "start_time": "2023-12-18T06:23:53.771345Z"
    }
   },
   "outputs": [],
   "source": [
    "import os\n",
    "import appbuilder\n",
    "\n",
    "# 使用组件之前，请前往千帆AppBuilder官网创建密钥，流程详见：https://cloud.baidu.com/doc/AppBuilder/s/Olq6grrt6#1、创建密钥\n",
    "os.environ[\"APPBUILDER_TOKEN\"] = '...'\n",
    "\n",
    "component = appbuilder.Playground(\n",
    "    prompt_template=\"{query}\",\n",
    "    model=\"ERNIE-Bot\"\n",
    ")\n",
    "\n",
    "agent = appbuilder.AgentRuntime(component=component)\n",
    "agent.serve(port=8091)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b71e24eb",
   "metadata": {},
   "source": [
    "通过 Shell 命令测试启动的服务, 请求 Body 为组件 run 方法的入参：\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "12c71fa5",
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "curl --location 'http://0.0.0.0:8091/chat' \\\n",
    "--header 'Content-Type: application/json' \\\n",
    "--data '{\n",
    "    \"message\": \"海淀区的面积是多少\",\n",
    "    \"stream\": false\n",
    "}'"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "5fc5bc38-6bc5-4187-a8fd-f802d77d89fa",
   "metadata": {},
   "source": [
    "## AgentRuntime 参数说明"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2364c35",
   "metadata": {},
   "source": [
    "### 1. 类初始化参数说明\n",
    "\n",
    "AgentRuntime 初始化接受两个参数。\n",
    "\n",
    "| 参数名称 | 参数类型 | 是否必须 | 描述 | 示例值 |\n",
    "|--|--|--|--|--|\n",
    "| component | Component | 是 | 可运行的 Component, 该 Component 需要实现 run(message, stream, **args) 方法。 | Playground(prompt_template=\"{query}\", model=\"ERNIE-Bot\") |\n",
    "| user_session_config | sqlalchemy.engine.URL\\|Str\\|None | 否 | 会话 Session 数据存储的数据库配置，遵循 sqlalchemy 后端定义，可参考[文档](https://docs.sqlalchemy.org/en/20/core/engines.html#backend-specific-urls)。默认使用 sqlite:///user_session.db，即本地的 SQLite 存储 | \"sqlite:///user_session.db\" |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "62e1af06",
   "metadata": {},
   "source": [
    "### 2. API 服务参数\n",
    "\n",
    "#### 2.1 请求参数\n",
    "\n",
    "**接口定义**\n",
    "\n",
    "| URL | Method |\n",
    "|--|--|\n",
    "| /chat | POST |\n",
    "\n",
    "**Header 参数**\n",
    "\n",
    "| 参数名称 | 是否必须 | 描述 | 示例值 |\n",
    "|--|--|--|--|\n",
    "| Content-Type | 是 | 必须设置为\"application/json\" | \"application/json\" |\n",
    "| X-Appbuilder-Token | 否 | 开启请求时认证能力时需要带入 APPBUILDER_TOKEN 进行鉴权 | 前往千帆AppBuilder官网创建密钥，流程详见[文档](https://cloud.baidu.com/doc/AppBuilder/s/Olq6grrt6#1、创建密钥) |\n",
    "\n",
    "**Body 参数**\n",
    "\n",
    "| 参数名称 | 参数类型 | 是否必须 | 描述 | 示例值 |\n",
    "|--|--|--|--|--|\n",
    "| message | Any | 是 | 透传到 component 的 run 方法的 message 参数 | \"海淀区的面积是多少\" |\n",
    "| stream | Bool | 否 | 是否流式调用。透传到 component 的 run 方法的 stream 参数。默认为 false | false |\n",
    "| session_id | Str | 否 | 用于标示同一个会话（Session）。如果不传该值，后端会自动生成 session_id，在响应参数中返回 | \"99680089-5acb-4298-9ade-a1a3f6c28102\" |\n",
    "| 其他参数 | Any | 否 | 透传到 component 的 run 方法 | - |\n",
    "\n",
    "\n",
    "#### 2.2 响应参数\n",
    "分为非流式响应和流式响应。\n",
    "\n",
    "**非流式响应**\n",
    "\n",
    "| 参数名称 | 参数类型 | 描述 | 示例值 |\n",
    "|--|--|--|--|\n",
    "| code | Int | 错误码。值为0表示成功，否则为失败。非0错误详见错误码部分描述 | 0 |\n",
    "| message | Str | 错误信息描述。 | \"Missing input variable query in message ['海淀区的面积是多少']\" |\n",
    "| result | Object | 请求结果 | - |\n",
    "| + answer_message | Object | 组件返回值，由返回的 Message 序列化得到 | {\"content\":\"海淀区是北京市的一个区，位于北京市主城区西部和西北部，东与西城区、朝阳区相邻，南与丰台区毗连，西与石景山区、门头沟区交界，北与昌平区接壤。海淀区的面积为**431平方千米**，约占北京市总面积的2.6%。\",\"extra\":{},\"id\":\"6b4e5019-a708-4bc5-a6ec-595fb4285677\",\"mtype\":\"dict\",\"name\":\"msg\"} |\n",
    "| + session_id | Str | 用于标示同一个会话（Session） | \"99680089-5acb-4298-9ade-a1a3f6c28102\" |\n",
    "\n",
    "**流式响应**\n",
    "\n",
    "流式数据以追加的形式返回。流式和非流式的数据结构一致，不再描述。\n",
    "\n",
    "#### 2.3 响应示例\n",
    "\n",
    "分为非流式响应和流式响应。\n",
    "\n",
    "**非流式响应**\n",
    "\n",
    "```shell\n",
    "{\n",
    "  \"code\": 0,\n",
    "  \"message\": \"\",\n",
    "  \"result\": {\n",
    "    \"answer_message\": {\n",
    "      \"content\": \"海淀区是北京市的一个区，位于北京市主城区西部和西北部，东与西城区、朝阳区相邻，南与丰台区毗连，西与石景山区、门头沟区交界，北与昌平区接壤。海淀区的面积为**431平方千米**，约占北京市总面积的2.6%。\",\n",
    "      \"extra\": {},\n",
    "      \"id\": \"6b4e5019-a708-4bc5-a6ec-595fb4285677\",\n",
    "      \"mtype\": \"dict\",\n",
    "      \"name\": \"msg\"\n",
    "    },\n",
    "    \"session_id\": \"99680089-5acb-4298-9ade-a1a3f6c28102\"\n",
    "  }\n",
    "}\n",
    "```\n",
    "\n",
    "**流式响应**\n",
    "\n",
    "```shell\n",
    "data: {\"code\": 0, \"message\": \"\", \"result\": {\"session_id\": \"663303a9-d83d-481f-a084-872ece87989c\", \"answer_message\": {\"content\": \"海淀区\", \"extra\": {}}}}\n",
    "\n",
    "data: {\"code\": 0, \"message\": \"\", \"result\": {\"session_id\": \"663303a9-d83d-481f-a084-872ece87989c\", \"answer_message\": {\"content\": \"，隶属于北京市，位于北京市主城区西部和西北部，东与西城区、朝阳区相邻，南与丰台区毗连，\", \"extra\": {}}}}\n",
    "\n",
    "data: {\"code\": 0, \"message\": \"\", \"result\": {\"session_id\": \"663303a9-d83d-481f-a084-872ece87989c\", \"answer_message\": {\"content\": \"西与石景山区、门头沟区交界，北与昌平区接壤，总面积**431平方千米**。\", \"extra\": {}}}}\n",
    "\n",
    "data: {\"code\": 0, \"message\": \"\", \"result\": {\"session_id\": \"663303a9-d83d-481f-a084-872ece87989c\", \"answer_message\": {\"content\": \"\", \"extra\": {}}}}\n",
    "```\n",
    "\n",
    "#### 2.4 错误码\n",
    "| 错误码 | 描述 |\n",
    "|--|--|\n",
    "| 400 | 客户端请求参数错误 |\n",
    "| 1000 | 服务端执行错误 |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "61923b00",
   "metadata": {},
   "source": [
    "## 高级用法"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a2303c76",
   "metadata": {},
   "source": [
    "### 1. 一键服务化组件 \n",
    "AgentRuntime 可以快速组件以服务的形式运行，支持 API 调用和对话框交互。\n",
    "\n",
    "**1.1 API调用**\n",
    "\n",
    "API 调用的基础用法在快速开始小结已经给出，这里不再赘述。\n",
    "\n",
    "下面介绍使用 `gunicorn` 启动生产级 Web 服务的方法，`gunicorn` 是一个适用于 UNIX 的 Python WSGI HTTP 服务器，详见[项目链接](https://github.com/benoitc/gunicorn)。\n",
    "\n",
    "首先创建 `app.py` 文件，暴露 Flask App："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fde5cc94",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import appbuilder\n",
    "\n",
    "# 使用组件之前，请前往千帆AppBuilder官网创建密钥，流程详见：https://cloud.baidu.com/doc/AppBuilder/s/Olq6grrt6#1、创建密钥\n",
    "os.environ[\"APPBUILDER_TOKEN\"] = '...'\n",
    "\n",
    "def get_flask_app():\n",
    "    component = appbuilder.Playground(\n",
    "        prompt_template=\"{query}\",\n",
    "        model=\"ERNIE-Bot\"\n",
    "    )\n",
    "    agent = appbuilder.AgentRuntime(component=component)\n",
    "    return agent.create_flask_app()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a41ef57b",
   "metadata": {},
   "source": [
    "基于 `gunicorn` 启动生产级服务："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2077833f",
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "# 服务工作进程数\n",
    "SERVER_WORKER_AMOUNT=8\n",
    "# 服务工作进程启动方式\n",
    "SERVER_WORKER_CLASS=gevent\n",
    "# 服务超时时间\n",
    "GUNICORN_TIMEOUT=60\n",
    "\n",
    "gunicorn \\\n",
    "  --bind \"0.0.0.0:8091\" \\\n",
    "  --workers ${SERVER_WORKER_AMOUNT} \\\n",
    "  --worker-class ${SERVER_WORKER_CLASS} \\\n",
    "  --timeout ${GUNICORN_TIMEOUT} \\\n",
    "  \"app:get_flask_app()\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "673c7565",
   "metadata": {},
   "source": [
    "**1.2 对话框交互**\n",
    "\n",
    "基于 chainlit 的对话框交互对被服务化的组件的 message 参数更加严格，要求能够接受 Str 的基础类型。\n",
    "\n",
    "执行下面的代码，会启动一个 chainlit 页面，页面地址：0.0.0.0:8091"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e485544f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import appbuilder\n",
    "\n",
    "# 使用组件之前，请前往千帆AppBuilder官网创建密钥，流程详见：https://cloud.baidu.com/doc/AppBuilder/s/Olq6grrt6#1、创建密钥\n",
    "os.environ[\"APPBUILDER_TOKEN\"] = '...'\n",
    "\n",
    "component = appbuilder.Playground(\n",
    "    prompt_template=\"{query}\",\n",
    "    model=\"ERNIE-Bot\"\n",
    ")\n",
    "\n",
    "agent = appbuilder.AgentRuntime(component=component)\n",
    "agent.chainlit_demo(port=8091)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d63bece",
   "metadata": {},
   "source": [
    "Chainlit Demo页面示意图如下所示，\n",
    "\n",
    "![chainlit demo](image/agent_runtime_with_chainlit_demo.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a074f367",
   "metadata": {},
   "source": [
    "**1.3 对话框交互AppBuilderClient**\n",
    "\n",
    "基于 chainlit 的对话框交互AppBuilderClient，可实现对话交互。支持工作流Agent、自主规划Agent应用。\n",
    "\n",
    "执行下面的代码，会启动一个 chainlit 页面，页面地址：0.0.0.0:8091。可在页面上上传文档（可选）、执行对话。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0a75e035",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import appbuilder\n",
    "\n",
    "# 使用组件之前，请前往千帆AppBuilder官网创建密钥，流程详见：https://cloud.baidu.com/doc/AppBuilder/s/Olq6grrt6#1、创建密钥\n",
    "os.environ[\"APPBUILDER_TOKEN\"] = \"...\"\n",
    "# 使用之前，在官网个人空间获取应用ID，如下图\n",
    "app_id= \"...\"\n",
    "client = appbuilder.AppBuilderClient(app_id)\n",
    "agent = appbuilder.AgentRuntime(client)\n",
    "agent.chainlit_agent(port=8091)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5162e29",
   "metadata": {},
   "source": [
    "在官网个人空间获取应用ID\n",
    "![get app_id](../app_builder_resources/app_id.png)\n",
    "\n",
    "使用服务上传文件并对话示例图如下所示\n",
    "![chainlit demo](./image/agent_runtime_with_chainlit_agent.png)\n",
    "\n",
    "使用工作流Agent应用对话示例如下图所示\n",
    "![chainlit demo](./image/agent_runtime_with_chainlit_chatflow.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2392f46d",
   "metadata": {},
   "source": [
    "### 2. Session 数据管理\n",
    "AgentRuntime 提供 Session 数据的管理功能，允许跟踪和存储用户会话数据。一般只有在二次开发的组件需要使用该能力。\n",
    "\n",
    "**2.1 二次开发组件**\n",
    "\n",
    "二次开发的组件需要重写组件的 run(message, stream, **args)方法，并且至少需要有 message 和 stream 两个参数。\n",
    "\n",
    "下面基于 QueryRewrite 和 Playground 两个组件，开发 PlaygroundWithHistory 组件，该组件需要对会话数据进行操作。\n",
    "\n",
    "当使用 Component 独立运行时，会话数据会被存储于内存。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "079048e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import logging\n",
    "from appbuilder.core.component import Component\n",
    "from appbuilder import (\n",
    "    AgentRuntime, UserSession, Message, QueryRewrite, Playground,\n",
    ")\n",
    "\n",
    "# 使用组件之前，请前往千帆AppBuilder官网创建密钥，流程详见：https://cloud.baidu.com/doc/AppBuilder/s/Olq6grrt6#1、创建密钥\n",
    "os.environ[\"APPBUILDER_TOKEN\"] = '...'\n",
    "\n",
    "class PlaygroundWithHistory(Component):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.query_rewrite = QueryRewrite(model=\"Qianfan-Agent-Speed-8K\")\n",
    "        self.playground = Playground(\n",
    "            prompt_template=\"{query}\",\n",
    "            model=\"ERNIE-Bot\"\n",
    "        )\n",
    "\n",
    "    def run(self, message: Message, stream: bool=False):\n",
    "        user_session = UserSession()\n",
    "        # 获取 Session 历史数据\n",
    "        history_queries = user_session.get_history(\"query\", limit=1)\n",
    "        history_answers = user_session.get_history(\"answer\", limit=1)\n",
    "\n",
    "        # query 改写\n",
    "        if history_queries and history_answers:\n",
    "            history = []\n",
    "            for query, answer in zip(history_queries, history_answers):\n",
    "                history.extend([query.content, answer.content])\n",
    "            logging.info(f\"history: {history}\")\n",
    "            message = self.query_rewrite(\n",
    "                Message(history + [message.content]), rewrite_type=\"带机器人回复\")\n",
    "        logging.info(f\"message: {message}\") \n",
    "\n",
    "        # 执行 playground\n",
    "        answer = self.playground.run(message, stream)\n",
    "\n",
    "        # 保存本轮数据\n",
    "        user_session.append({\n",
    "            \"query\": message,\n",
    "            \"answer\": answer,\n",
    "        }) \n",
    "        return answer\n",
    "\n",
    "# component 可以独立运行，session数据会被保存于内存\n",
    "playground_with_history_component = PlaygroundWithHistory()\n",
    "print(playground_with_history_component.run(Message(\"海淀区的面积是多少\"), stream=False))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "480fd56d",
   "metadata": {},
   "source": [
    "**2.2 会话数据存储数据库**\n",
    "\n",
    "使用 AgentRuntime 对 Component 服务化，会话数据会被存储于数据库。\n",
    "下面的代码以 SQLite 为例展示该能力，更多数据库配置详见[文档](https://docs.sqlalchemy.org/en/20/core/engines.html#backend-specific-urls)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "111b11de",
   "metadata": {},
   "outputs": [],
   "source": [
    "user_session_config = \"sqlite:///foo.db\"\n",
    "agent = appbuilder.AgentRuntime(\n",
    "    component=playground_with_history_component, \n",
    "    user_session_config=user_session_config)\n",
    "agent.serve(port=8091)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e7dc38ec",
   "metadata": {},
   "source": [
    "### 3. 请求时鉴权\n",
    "AgentRuntime 支持在请求时进行认证，确保安全性。\n",
    "\n",
    "使用该能力，在初始化组件时需要设置 lazy 鉴权："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2125bf4f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import appbuilder\n",
    "\n",
    "# 无需配置 APPBUILDER_TOKEN 环境变量\n",
    "\n",
    "component = appbuilder.Playground(\n",
    "    prompt_template=\"{query}\",\n",
    "    model=\"ERNIE-Bot\",\n",
    "    lazy_certification=True, # 设置 lazy 鉴权，在创建时不进行认证\n",
    ")\n",
    "\n",
    "agent = appbuilder.AgentRuntime(component=component)\n",
    "agent.serve(port=8091)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bbf35a0a",
   "metadata": {},
   "source": [
    "当初始化组件时进行了 lazy 鉴权，请求时请求头必须带上 `X-Appbuilder-Token` （即Appbuilder密钥，获取流程详见[千帆AppBuilder官网创建密钥](https://cloud.baidu.com/doc/AppBuilder/s/Olq6grrt6#1、创建密钥)）进行鉴权："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "60dcfa37",
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "curl --location 'http://0.0.0.0:8091/chat' \\\n",
    "    --header 'Content-Type: application/json' \\\n",
    "    --header 'X-Appbuilder-Token: ...' \\\n",
    "    --data '{\n",
    "        \"message\": \"海淀区的面积是多少\",\n",
    "        \"stream\": false\n",
    "    }'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8584416",
   "metadata": {},
   "source": [
    "### 4. 查看user_session.db储存信息\n",
    "\n",
    "\n",
    "使用该能力，查看用户对话信息。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "id": "9bbeb156",
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "import sqlite3  \n",
    "  \n",
    "# 连接到 SQLite 数据库  \n",
    "# 如果文件不存在，会自动在当前目录创建:  \n",
    "user_session_path = '本地user_session.db地址' \n",
    "conn = sqlite3.connect(user_session_path)  \n",
    "cursor = conn.cursor()  "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "54cce03b",
   "metadata": {},
   "source": [
    "执行 SQL 语句，列出SQLite数据库中的所有表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "id": "f4ca2963",
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[('appbuilder_session_messages',)]\n"
     ]
    }
   ],
   "source": [
    "# 执行一条 SQL 语句，列出所有表  \n",
    "cursor.execute(\"SELECT name FROM sqlite_master WHERE type='table';\")  \n",
    "print(cursor.fetchall())  "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e5b838f4",
   "metadata": {},
   "source": [
    "查询appbuilder_session_messages表的列信息,appbuilder_session_messages表的列信息为:\n",
    "- id\n",
    "- session_id\n",
    "- request_id\n",
    "- message_key\n",
    "- message_value\n",
    "- created_at\n",
    "- updated_at\n",
    "- deleted"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "1ac388d7",
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "id\n",
      "session_id\n",
      "request_id\n",
      "message_key\n",
      "message_value\n",
      "created_at\n",
      "updated_at\n",
      "deleted\n"
     ]
    }
   ],
   "source": [
    "cursor.execute(\"PRAGMA table_info(appbuilder_session_messages);\")  \n",
    "columns_info = cursor.fetchall()  \n",
    "\n",
    "column_names = [info[1] for info in columns_info]  # info[1]是列名的位置  \n",
    "for column_name in column_names:  \n",
    "    print(column_name)   "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3965454f",
   "metadata": {},
   "source": [
    "查询表中的特定数据【以message_value信息为例】\n",
    "输出content、id、token_usage等信息"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "id": "2e6d9e45",
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'content': '你好', 'name': 'msg', 'mtype': 'str', 'id': '90c8d150-c7b9-44a4-ac77-50dd61ee329a'}\n",
      "{'content': '你好，我是百度研发的知识增强大语言模型，中文名是文心一言，英文名是ERNIE Bot。我能够与人对话互动，回答问题，协助创作，高效便捷地帮助人们获取信息、知识和灵感。', 'name': 'msg', 'mtype': 'dict', 'id': '0fc6c5f7-23bf-4f25-8555-69b4155908b7', 'extra': {}, 'token_usage': {'prompt_tokens': 2, 'completion_tokens': 42, 'total_tokens': 44}}\n",
      "{'content': '请介绍一下你自己', 'name': 'msg', 'mtype': 'dict', 'id': '4f5cf6d1-976e-456e-a632-93c4b2550523', 'extra': {'search_db': [{'content': '带机器人回复：请你扮演一个智能搜索改写补全机器人，请根据User的搜索历史以及对应的搜索结果，对最后一句话先进行主语继承改写，然后进行上下文信息补全，注意：不要改变原文的意思，答案要尽可能简洁，不要直接回答该问题，不要输出多于的内容。\\\\n\\\\n例子：\\\\n搜索历史：\\\\nUser：今天上午你干嘛了\\\\nAssistant：去打篮球啦\\\\nUser：好玩吗？\\\\n答案：\\\\n打篮球好玩吗？', 'dataset_id': '1f777fa3-26db-4237-98d5-075abc07a84f', 'dataset_name': '多轮改写Prompt', 'document_id': '92e0f30d-1f30-46f0-8377-59ab0fb6eb93', 'document_name': '多轮改写prompt_带机器人回复.txt', 'id': '61657591-f610-44f0-84ec-67cedcb66447', 'mock_id': '1', 'position': 0, 'score': 0.511053, 'sentences': [{'content': '带机器人回复：请你扮演一个智能搜索改写补全机器人，请根据User的搜索历史以及对应的搜索结果，对最后一句话先进行主语继承改写，然后进行上下文信息补全，注意：不要改变原文的意思，答案要尽可能简洁，不要直接回答该问题，不要输出多于的内容。\\\\n\\\\n例子：\\\\n搜索历史：\\\\nUser：今天上午你干嘛了\\\\nAssistant：去打篮球啦\\\\nUser：好玩吗？', 'id': '1f777fa3-26db-4237-98d5-075abc07a84f-5992356ea8c0c05485388623218e134e-975ec17bbf8206762df7cfb24a5cd85e-97468bdaf0accef718118a2b742d5cc0', 'score': 0.628708, 'source': None}], 'title': '多轮改写prompt_带机器人回复.txt', 'tokens': 0, 'type': 'engine', 'word_count': 188}]}, 'token_usage': {'prompt_tokens': 321, 'completion_tokens': 3, 'total_tokens': 324}}\n",
      "{'content': '您好，我是文心一言，英文名是ERNIE Bot。我能够与人对话互动，回答问题，协助创作，高效便捷地帮助人们获取信息、知识和灵感。', 'name': 'msg', 'mtype': 'dict', 'id': 'f769c850-f4e5-4d02-a62a-766fd8c8132e', 'extra': {}, 'token_usage': {'prompt_tokens': 4, 'completion_tokens': 33, 'total_tokens': 37}}\n",
      "{'content': '介绍一下baidu公司', 'name': 'msg', 'mtype': 'dict', 'id': '0ff3b298-7f01-4036-927d-722e00afaf33', 'extra': {'search_db': [{'content': '带机器人回复：请你扮演一个智能搜索改写补全机器人，请根据User的搜索历史以及对应的搜索结果，对最后一句话先进行主语继承改写，然后进行上下文信息补全，注意：不要改变原文的意思，答案要尽可能简洁，不要直接回答该问题，不要输出多于的内容。\\\\n\\\\n例子：\\\\n搜索历史：\\\\nUser：今天上午你干嘛了\\\\nAssistant：去打篮球啦\\\\nUser：好玩吗？\\\\n答案：\\\\n打篮球好玩吗？', 'dataset_id': '1f777fa3-26db-4237-98d5-075abc07a84f', 'dataset_name': '多轮改写Prompt', 'document_id': '92e0f30d-1f30-46f0-8377-59ab0fb6eb93', 'document_name': '多轮改写prompt_带机器人回复.txt', 'id': '61657591-f610-44f0-84ec-67cedcb66447', 'mock_id': '1', 'position': 0, 'score': 0.511053, 'sentences': [{'content': '带机器人回复：请你扮演一个智能搜索改写补全机器人，请根据User的搜索历史以及对应的搜索结果，对最后一句话先进行主语继承改写，然后进行上下文信息补全，注意：不要改变原文的意思，答案要尽可能简洁，不要直接回答该问题，不要输出多于的内容。\\\\n\\\\n例子：\\\\n搜索历史：\\\\nUser：今天上午你干嘛了\\\\nAssistant：去打篮球啦\\\\nUser：好玩吗？', 'id': '1f777fa3-26db-4237-98d5-075abc07a84f-5992356ea8c0c05485388623218e134e-975ec17bbf8206762df7cfb24a5cd85e-97468bdaf0accef718118a2b742d5cc0', 'score': 0.628708, 'source': None}], 'title': '多轮改写prompt_带机器人回复.txt', 'tokens': 0, 'type': 'engine', 'word_count': 188}]}, 'token_usage': {'prompt_tokens': 910, 'completion_tokens': 3, 'total_tokens': 913}}\n",
      "{'content': '百度公司是中国最大的互联网搜索引擎提供商之一，也是全球领先的AI公司。以下是对百度的详细介绍：\\n\\n一、公司概况\\n\\n百度（BIDU）是一家提供中文搜索引擎的公司，由李彦宏于2000年1月在北京中关村创立。经过多年的发展，百度已经从单一的搜索引擎服务商成功转型为内容生态与人工智能（AI）融合的互联网公司。百度的使命是“用科技让复杂的世界更简单”，其核心价值观包括“简单可依赖”。\\n\\n二、主要业务与产品\\n\\n1. 搜索业务：百度搜索是中国最大的中文搜索引擎，每天响应来自全球各地的搜索请求。除了传统的网页、图片、视频等搜索结果外，还提供了知识图谱、语音搜索等创新功能。\\n2. 移动生态业务：百度APP是百度移动生态的核心产品，围绕看、搜、听、问、购等核心场景为用户提供服务。此外，百度还拥有信息流、智能小程序、百度知道、百度文库等一系列移动生态产品。\\n3. 智能云业务：百度智能云是百度提供的云计算服务平台，为企业提供计算、存储、网络等基础设施服务以及人工智能、大数据等中间件服务。\\n4. 智能驾驶业务：百度在自动驾驶领域具有领先地位，其Apollo自动驾驶平台已经发展出多种商业模式，包括自动驾驶技术解决方案、百度造车以及共享无人车等。\\n\\n三、财务状况与业绩表现\\n\\n根据百度发布的财报显示，其业绩表现亮眼。例如，在2023年，百度总营收达到了显著的水平，其中百度核心收入同比增长。这主要得益于公司在广告市场的持续领先地位以及非在线营销收入的增长。同时，百度在研发投入方面也保持了较高水平，以推动其AI技术的持续创新和发展。\\n\\n四、AI技术与创新\\n\\n百度在AI技术方面取得了显著成果。其文心大模型已经升级到4.0版本，用户规模超过了1亿。这一技术使得百度具备了与全球领先的AI产品相媲美的能力。此外，百度还在文字生成视频等领域进行了战略投资，以进一步拓展其业务范围并加强在AI领域的领先地位。\\n\\n综上所述，百度公司作为中国最大的互联网搜索引擎提供商和全球领先的AI公司之一，凭借其强大的技术实力和创新能力，在搜索、移动生态、智能云和智能驾驶等领域取得了显著的成果。', 'name': 'msg', 'mtype': 'dict', 'id': 'c4f02188-1206-4c02-be8e-1c5481428003', 'extra': {}, 'token_usage': {'prompt_tokens': 4, 'completion_tokens': 456, 'total_tokens': 460}}\n"
     ]
    }
   ],
   "source": [
    "import json\n",
    "cursor.execute(\"SELECT message_value FROM appbuilder_session_messages;\")  \n",
    "for row in cursor.fetchall():  \n",
    "    print(json.loads(row[0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ff82880",
   "metadata": {},
   "source": [
    "以id查询相关的agent_runtime信息"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "id": "e79e2554",
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "16010b88-d766-4524-81ee-37f96ceadb4d\n",
      "b2c9d058-4475-4258-ad90-4334f3d024d5\n",
      "0bdafb3d-f7e3-4187-bc1d-63cf51fbda29\n",
      "query\n",
      "{'content': '你好', 'name': 'msg', 'mtype': 'str', 'id': '90c8d150-c7b9-44a4-ac77-50dd61ee329a'}\n",
      "2024-07-30 15:01:10.949475\n",
      "2024-07-30 15:01:10.949485\n",
      "0\n",
      "4bd85fd0-2e5c-4de1-a47e-ea122f7e928c\n",
      "b2c9d058-4475-4258-ad90-4334f3d024d5\n",
      "0bdafb3d-f7e3-4187-bc1d-63cf51fbda29\n",
      "answer\n",
      "{'content': '你好，我是百度研发的知识增强大语言模型，中文名是文心一言，英文名是ERNIE Bot。我能够与人对话互动，回答问题，协助创作，高效便捷地帮助人们获取信息、知识和灵感。', 'name': 'msg', 'mtype': 'dict', 'id': '0fc6c5f7-23bf-4f25-8555-69b4155908b7', 'extra': {}, 'token_usage': {'prompt_tokens': 2, 'completion_tokens': 42, 'total_tokens': 44}}\n",
      "2024-07-30 15:01:10.955875\n",
      "2024-07-30 15:01:10.955884\n",
      "0\n",
      "d6e433fc-ef4d-4ade-9a63-fec600e95481\n",
      "b2c9d058-4475-4258-ad90-4334f3d024d5\n",
      "6300b76b-2307-4ed3-9f6d-e61dfc621ff8\n",
      "query\n",
      "{'content': '请介绍一下你自己', 'name': 'msg', 'mtype': 'dict', 'id': '4f5cf6d1-976e-456e-a632-93c4b2550523', 'extra': {'search_db': [{'content': '带机器人回复：请你扮演一个智能搜索改写补全机器人，请根据User的搜索历史以及对应的搜索结果，对最后一句话先进行主语继承改写，然后进行上下文信息补全，注意：不要改变原文的意思，答案要尽可能简洁，不要直接回答该问题，不要输出多于的内容。\\\\n\\\\n例子：\\\\n搜索历史：\\\\nUser：今天上午你干嘛了\\\\nAssistant：去打篮球啦\\\\nUser：好玩吗？\\\\n答案：\\\\n打篮球好玩吗？', 'dataset_id': '1f777fa3-26db-4237-98d5-075abc07a84f', 'dataset_name': '多轮改写Prompt', 'document_id': '92e0f30d-1f30-46f0-8377-59ab0fb6eb93', 'document_name': '多轮改写prompt_带机器人回复.txt', 'id': '61657591-f610-44f0-84ec-67cedcb66447', 'mock_id': '1', 'position': 0, 'score': 0.511053, 'sentences': [{'content': '带机器人回复：请你扮演一个智能搜索改写补全机器人，请根据User的搜索历史以及对应的搜索结果，对最后一句话先进行主语继承改写，然后进行上下文信息补全，注意：不要改变原文的意思，答案要尽可能简洁，不要直接回答该问题，不要输出多于的内容。\\\\n\\\\n例子：\\\\n搜索历史：\\\\nUser：今天上午你干嘛了\\\\nAssistant：去打篮球啦\\\\nUser：好玩吗？', 'id': '1f777fa3-26db-4237-98d5-075abc07a84f-5992356ea8c0c05485388623218e134e-975ec17bbf8206762df7cfb24a5cd85e-97468bdaf0accef718118a2b742d5cc0', 'score': 0.628708, 'source': None}], 'title': '多轮改写prompt_带机器人回复.txt', 'tokens': 0, 'type': 'engine', 'word_count': 188}]}, 'token_usage': {'prompt_tokens': 321, 'completion_tokens': 3, 'total_tokens': 324}}\n",
      "2024-07-30 15:01:19.161269\n",
      "2024-07-30 15:01:19.161272\n",
      "0\n",
      "f0d76f00-93be-4d7c-a6b3-a9583fd677ad\n",
      "b2c9d058-4475-4258-ad90-4334f3d024d5\n",
      "6300b76b-2307-4ed3-9f6d-e61dfc621ff8\n",
      "answer\n",
      "{'content': '您好，我是文心一言，英文名是ERNIE Bot。我能够与人对话互动，回答问题，协助创作，高效便捷地帮助人们获取信息、知识和灵感。', 'name': 'msg', 'mtype': 'dict', 'id': 'f769c850-f4e5-4d02-a62a-766fd8c8132e', 'extra': {}, 'token_usage': {'prompt_tokens': 4, 'completion_tokens': 33, 'total_tokens': 37}}\n",
      "2024-07-30 15:01:19.163405\n",
      "2024-07-30 15:01:19.163411\n",
      "0\n",
      "936c394a-a3fa-48fd-a72f-b1778ebc35e4\n",
      "b2c9d058-4475-4258-ad90-4334f3d024d5\n",
      "5eb09e91-6496-44d9-9303-a4790e97f61c\n",
      "query\n",
      "{'content': '介绍一下baidu公司', 'name': 'msg', 'mtype': 'dict', 'id': '0ff3b298-7f01-4036-927d-722e00afaf33', 'extra': {'search_db': [{'content': '带机器人回复：请你扮演一个智能搜索改写补全机器人，请根据User的搜索历史以及对应的搜索结果，对最后一句话先进行主语继承改写，然后进行上下文信息补全，注意：不要改变原文的意思，答案要尽可能简洁，不要直接回答该问题，不要输出多于的内容。\\\\n\\\\n例子：\\\\n搜索历史：\\\\nUser：今天上午你干嘛了\\\\nAssistant：去打篮球啦\\\\nUser：好玩吗？\\\\n答案：\\\\n打篮球好玩吗？', 'dataset_id': '1f777fa3-26db-4237-98d5-075abc07a84f', 'dataset_name': '多轮改写Prompt', 'document_id': '92e0f30d-1f30-46f0-8377-59ab0fb6eb93', 'document_name': '多轮改写prompt_带机器人回复.txt', 'id': '61657591-f610-44f0-84ec-67cedcb66447', 'mock_id': '1', 'position': 0, 'score': 0.511053, 'sentences': [{'content': '带机器人回复：请你扮演一个智能搜索改写补全机器人，请根据User的搜索历史以及对应的搜索结果，对最后一句话先进行主语继承改写，然后进行上下文信息补全，注意：不要改变原文的意思，答案要尽可能简洁，不要直接回答该问题，不要输出多于的内容。\\\\n\\\\n例子：\\\\n搜索历史：\\\\nUser：今天上午你干嘛了\\\\nAssistant：去打篮球啦\\\\nUser：好玩吗？', 'id': '1f777fa3-26db-4237-98d5-075abc07a84f-5992356ea8c0c05485388623218e134e-975ec17bbf8206762df7cfb24a5cd85e-97468bdaf0accef718118a2b742d5cc0', 'score': 0.628708, 'source': None}], 'title': '多轮改写prompt_带机器人回复.txt', 'tokens': 0, 'type': 'engine', 'word_count': 188}]}, 'token_usage': {'prompt_tokens': 910, 'completion_tokens': 3, 'total_tokens': 913}}\n",
      "2024-07-30 15:02:21.551493\n",
      "2024-07-30 15:02:21.551529\n",
      "0\n",
      "5cd9d7ef-e26f-48ca-bd55-de2861cd4e84\n",
      "b2c9d058-4475-4258-ad90-4334f3d024d5\n",
      "5eb09e91-6496-44d9-9303-a4790e97f61c\n",
      "answer\n",
      "{'content': '百度公司是中国最大的互联网搜索引擎提供商之一，也是全球领先的AI公司。以下是对百度的详细介绍：\\n\\n一、公司概况\\n\\n百度（BIDU）是一家提供中文搜索引擎的公司，由李彦宏于2000年1月在北京中关村创立。经过多年的发展，百度已经从单一的搜索引擎服务商成功转型为内容生态与人工智能（AI）融合的互联网公司。百度的使命是“用科技让复杂的世界更简单”，其核心价值观包括“简单可依赖”。\\n\\n二、主要业务与产品\\n\\n1. 搜索业务：百度搜索是中国最大的中文搜索引擎，每天响应来自全球各地的搜索请求。除了传统的网页、图片、视频等搜索结果外，还提供了知识图谱、语音搜索等创新功能。\\n2. 移动生态业务：百度APP是百度移动生态的核心产品，围绕看、搜、听、问、购等核心场景为用户提供服务。此外，百度还拥有信息流、智能小程序、百度知道、百度文库等一系列移动生态产品。\\n3. 智能云业务：百度智能云是百度提供的云计算服务平台，为企业提供计算、存储、网络等基础设施服务以及人工智能、大数据等中间件服务。\\n4. 智能驾驶业务：百度在自动驾驶领域具有领先地位，其Apollo自动驾驶平台已经发展出多种商业模式，包括自动驾驶技术解决方案、百度造车以及共享无人车等。\\n\\n三、财务状况与业绩表现\\n\\n根据百度发布的财报显示，其业绩表现亮眼。例如，在2023年，百度总营收达到了显著的水平，其中百度核心收入同比增长。这主要得益于公司在广告市场的持续领先地位以及非在线营销收入的增长。同时，百度在研发投入方面也保持了较高水平，以推动其AI技术的持续创新和发展。\\n\\n四、AI技术与创新\\n\\n百度在AI技术方面取得了显著成果。其文心大模型已经升级到4.0版本，用户规模超过了1亿。这一技术使得百度具备了与全球领先的AI产品相媲美的能力。此外，百度还在文字生成视频等领域进行了战略投资，以进一步拓展其业务范围并加强在AI领域的领先地位。\\n\\n综上所述，百度公司作为中国最大的互联网搜索引擎提供商和全球领先的AI公司之一，凭借其强大的技术实力和创新能力，在搜索、移动生态、智能云和智能驾驶等领域取得了显著的成果。', 'name': 'msg', 'mtype': 'dict', 'id': 'c4f02188-1206-4c02-be8e-1c5481428003', 'extra': {}, 'token_usage': {'prompt_tokens': 4, 'completion_tokens': 456, 'total_tokens': 460}}\n",
      "2024-07-30 15:02:21.557667\n",
      "2024-07-30 15:02:21.557671\n",
      "0\n"
     ]
    }
   ],
   "source": [
    "cursor.execute(\"SELECT * FROM appbuilder_session_messages WHERE session_id = 'b2c9d058-4475-4258-ad90-4334f3d024d5';\")  \n",
    "for tuple in cursor.fetchall():\n",
    "    for message in tuple:\n",
    "        try: \n",
    "            message = json.loads(message)\n",
    "            print(message)\n",
    "        except:\n",
    "            print(message)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
